package com.jsg.sl651.codec.impl;

import com.jsg.sl651.codec.FrameEncoder;
import com.jsg.sl651.entity.frame.FrameMessageWrapper;
import com.jsg.sl651.entity.frame.header.IdentificationAndLength;
import com.jsg.sl651.entity.frame.header.MessageHeader;
import com.jsg.sl651.enums.MessageDirection;
import com.jsg.sl651.util.SL651Tool;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;

public class FrameEncoderImpl implements FrameEncoder {
    /**
     * 将消息包装成帧格式
     * @param frameWrapper 消息包装
     * @return ByteBuf
     */
    @Override
    public ByteBuf encode(FrameMessageWrapper frameWrapper) {
        ByteBuf buf = Unpooled.buffer();
        // 开始写入
        // 1. 报文开始标志符
        buf.writeBytes(frameWrapper.getStartSymbolBytes());
        // 2. 报文头
        MessageHeader header = frameWrapper.getHeader();
        // 2.1 先是测站地址
        buf.writeBytes(header.getRemoteTelemetryStationAddress().getMessageBytes(frameWrapper.getMessageType()));
        // 2.2 中心站地址
        buf.writeBytes(header.getBodyCentralStationAddress(frameWrapper.getMessageType()));
        // 2.3 密码
        buf.writeBytes(header.getBodyPassword(frameWrapper.getMessageType()));
        // 2.4 功能码
        buf.writeByte(header.getFunction().getCode());
        // 2.6 报文下行标识及长度
        // 获取消息体
        byte[] encode = frameWrapper.getBody().encode(frameWrapper.getMessageType());
        IdentificationAndLength identificationAndLength = new IdentificationAndLength(MessageDirection.DOWN, encode.length);
        buf.writeBytes(identificationAndLength.toBodyBytes(frameWrapper.getMessageType()));
        // 报文起始符号
        buf.writeBytes(header.getStartOfTextSymbol().getMessageBytes(frameWrapper.getMessageType()));
        if (frameWrapper.getHeader().isM3()) {
            // 需要写入分包信息
            buf.writeBytes(header.getPacketInfo().toBodyBytes(frameWrapper.getMessageType()));
        }
        buf.writeBytes(encode);
        buf.writeBytes(frameWrapper.getEndOfTextSymbol().getMessageBytes(frameWrapper.getMessageType()));
        // 计算CRC
        // 获取buf中的所有字节
        byte[] bytes = new byte[buf.readableBytes()];
        buf.getBytes(buf.readerIndex(), bytes);
        buf.writeBytes(SL651Tool.getSl651Crc(bytes));
        return buf;
    }
}
